package enums;

import iface.KeyEnum;
import iface.OperatingEnum;

/**
 * Enumerator which contains mathematical operators.
 * 
 * @author Marcus
 * 
 */
public enum Operator implements KeyEnum, OperatingEnum {
	PLUS("+", 0) {
		/**
		 * {@inheritDoc}
		 * 
		 * <p>
		 * Adds {@code a} and {@code b}.
		 * </p>
		 */
		@Override
		public double performOperation(double a, double b) {
			return a + b;
		}
	},
	MINUS("-", 0) {
		/**
		 * {@inheritDoc}
		 * 
		 * <p>
		 * Subtract from {@code a} the number {@code b}.
		 * </p>
		 */
		@Override
		public double performOperation(double a, double b) {
			return a - b;
		}
	},
	MULTIPLY("*", 1) {
		/**
		 * {@inheritDoc}
		 * 
		 * <p>
		 * Multiplies {@code a} with {@code b}.
		 * </p>
		 */
		@Override
		public double performOperation(double a, double b) {
			return a * b;
		}
	},
	DIVIDE("/", 1) {
		/**
		 * {@inheritDoc}
		 * 
		 * <p>
		 * Divides {@code a} through {@code b}.
		 * </p>
		 */
		@Override
		public double performOperation(double a, double b) {
			if (b == 0) {
				throw new IllegalArgumentException("b cannot be '0'");
			}

			return a / b;
		}
	},
	OPEN("(", 2), CLOSE(")", 2), POWER("^", 1) {
		/**
		 * {@inheritDoc}
		 * 
		 * <p>
		 * calculate the power of a^b.
		 * </p>
		 */
		@Override
		public double performOperation(double a, double b) {
			return Math.pow(a, b);
		}
	};

	private String operatorKey;
	private int priority;

	private Operator(String operator, int pri) {
		this.operatorKey = operator;
		this.priority = pri;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @throws IllegalStateException
	 *             if there is no operation implemented for this
	 *             {@link Operator}.
	 */
	@Override
	public double performOperation(double a, double b) {
		throw new IllegalStateException(
				"There is no implemented operation for this '"
						+ this.toString() + "' enum.");
	}

	public int getPriority() {
		return this.priority;
	}

	public String getOperatorString() {
		return this.operatorKey;
	}

	public static Operator getOperatorEnum(String operator) {
		for (Operator operatorEnum : Operator.values()) {
			if (operatorEnum.getOperatorString().equals(operator)) {
				return operatorEnum;
			}
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getKey() {
		return this.operatorKey;
	}

}
